/*
 * Node.hpp
 *
 *  Created on: 2009-9-26
 *      Author: ws
 */

#ifndef NODE_HPP_
#define NODE_HPP_
//represent the oper

#include<vector>
#include<string>
#include<map>

#include"UsageFU.hpp"
#include"NodeSequence.hpp"
#include"RegMask.hpp"
#include"Value.hpp"
#include"Dep.hpp"
#include"common.hpp"

class UsageFU;
class Dep;
class Operand;
class Reg_Manager;
class LiveRang;

class Node;


class Node {
	friend class NodeSequence;
	friend class NodeSequence::iterator;
	friend class Region;
	friend class Dep;
	friend class NodeProductor;
	friend class RegionBuilder;
	//the predicator
	struct predecessor_less;
public:
	Node(unsigned int flag):
		dest(operands[DEST]),
		src(operands[SRC]),
		src_mem(operands[SRC_MEM]),
		dest_mem(operands[DEST_MEM]),
		ctr(operands[CTR]),
		implict_src(operands[IMPLICT_SRC]),
		implict_dest(operands[IMPLICT_DEST]),
		type_flag(flag)
	{
	}

private:
	/*
	 * ==============================================================================
 	 * note: the "prev" and "next" memeber field must be on the begin of definition
 	 * ===============================================================================
 	 */
	Node *prev, *next;
	Region* region;

public:
	/*
	 * ================================
	 * NodeSequence Method
	 * ================================
	 */
	void insert_before(Node*n);
	void insert_after(Node* n);

protected:
	std::vector<Value*>  operands[OPD_SUM];
	std::vector<Value*> & dest ;
	std::vector<Value*> & src ;
	std::vector<Value*> & src_mem ;
	std::vector<Value*> & dest_mem;
	std::vector<Value*> & ctr ;
	std::vector<Value*> & implict_src ;
	std::vector<Value*> & implict_dest ;

	std::vector<location> regs[2];
protected:
	//this is called by the subclass
	inline void init_defs_and_uses()
	{
		init_defs();
		init_uses();
	}
private:
	void init_defs();
	void init_uses();
/*
 * ========================================================
 *
 * 				Value Iterator
 * ========================================================
 */
public:
	enum Half{ USE, DEF};
	template<enum Half half>
	class VIter{
		int i ; 
		Node * n;
	public:
		VIter(Node* n, int i):n(n), i(i){}
		RegValue* operator ->()
		{
			return  RegValue_cast(n->get_value(n->regs[half][i]));
		}	
		RegValue& operator * ()
		{
			return  *(RegValue_cast(n->get_value(n->regs[half][i])));
		}
		location loc()
		{
			return n->regs[half][i];
		}
		VIter  operator ++ (int)
		{
			int k = i;
			i++;
			return VIter<half>(n, k);
		}
		VIter & operator ++ ()
		{
			i++;
			return *this;
		}

		friend  bool operator ==(const VIter<half> &x, const VIter<half> &y);
		friend  bool operator !=(const VIter<half> &x, const VIter<half> &y);
	};
	typedef VIter<USE> UVIter;
	typedef VIter<DEF> DVIter;
	UVIter uiter_begin();
	UVIter uiter_end();
	DVIter diter_begin();
	DVIter diter_end();
	//for the component cluster assign algorithm
	inline Value* get_value(const location& loc)
	{
		assert(operands[loc.operand_type].size() > loc.index);
		return operands[loc.operand_type][loc.index];
	}
/*=====================================================
 *			 miscellaneous
 * ===================================================
 */
private:
	int id; //for the print out  display
	int proc_opc; //processor opcode , for the start node is 0, for end node is -1;
	unsigned int  type_flag;
public:
	inline int get_id()const{ return id; }
	int get_proc_opc()const { return proc_opc;}
	unsigned int get_type_flag()const { return type_flag;}
	std::string get_type_name()const ;

/*=======================================================
 *	DAG info
 *=======================================================
 */

private:
	bool visited;
	int earlist_time;
	int latest_time;
	//all the in_degree
	Dep_Sequence<Dep::IND> indeps;
	//all the out_degree
	Dep_Sequence<Dep::OUTD> outdeps;
public:
	void add_outdep(Dep *);
	void add_indep(Dep *);
	/*get all indep of */
	ODIter OUT_Dbegin(unsigned int flag)const;
	IDIter IN_Dbegin(unsigned int flag)const;
	Dep_Sequence<Dep::IND>& get_indep();
	Dep_Sequence<Dep::OUTD>& get_outdep();
	bool is_visited();
	void set_visited();
	void reset_visited();
	bool all_indep_is_visited(unsigned int flag) const;
	bool all_indep_is_visited(unsigned int flag, location & loc)const;
	bool all_outdep_is_visited  (unsigned int flag)const;
	bool all_outdep_is_visited  (unsigned int flag , location & loc)const;

	std::vector<Dep *> get_value_indep(Value* v, unsigned int flag);
	std::vector<Dep *> get_value_outdep(Value* v, unsigned int flag);

	/*
	 * sort the indeps for the depth first search
	 */
	void sort_indeps();
	int get_depth()const
	{
		return earlist_time;
	}
	void  set_depth(int depth)
	{
		earlist_time = depth;
	}

	void update_depth(int depth, unsigned int dep_flag);

	int get_heighth()const
	{
		return latest_time;
	}
	void set_heighth(int heighth)
	{
		latest_time = heighth;
	}

	std::vector<int> get_def_regs();
	std::vector<int> get_use_regs();
	//print function
	void print_outdeps();
	void print_indeps();
	void print()const;
/*====================================================================
 *
 * 	register allocation
 *====================================================================
 */
protected:
	bool allocated;
public:
	bool is_allocated()const {return allocated;}
	void mark_allocated() { allocated = true;}

	void src_assign_physical_register(int id, enum TargetInfo::PhysicalRegister physical_register);
	void dest_assign_physical_register(int id ,enum TargetInfo::PhysicalRegister physical_register);

	void assign_cluster(enum LOC_Type type, enum Core);
/*
 * deconstructor function
 */
	virtual ~Node()
	{
	}
};

#endif /* NODE_HPP_ */
